package osgi.common.services.job;

import static org.quartz.CronScheduleBuilder.cronSchedule;
import static org.quartz.JobBuilder.newJob;
import static org.quartz.TriggerBuilder.newTrigger;

import java.util.HashMap;

import org.osgi.service.component.ComponentContext;
import org.quartz.JobDataMap;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.Trigger;
import org.quartz.impl.StdSchedulerFactory;
import org.quartz.impl.matchers.EverythingMatcher;

import osgi.common.services.client.AbstractService;
import osgi.common.services.job.client.ICommonJob;

public class QuartzService extends AbstractService implements IQuartzService {

	
	protected Scheduler scheduler;

	protected HashMap<String, ICommonJob> registeredJobs;
    
	
	
	
	public QuartzService() {
		super();
		
		registeredJobs = new HashMap<String, ICommonJob>();
		
		this.serviceName = "Quartz Service - DEFAULT";

	}

	
	@Override
	public void shutdownScheduler() throws Exception {
		logger.info("shutdownScheduler() - start");

		scheduler.shutdown();

		logger.info("shutdownScheduler() - end");
	}

	
	@Override
	public void startScheduler() throws Exception {

		logger.info("startScheduler() - start");

		try {

			scheduler = StdSchedulerFactory.getDefaultScheduler();

			scheduler.getListenerManager().addJobListener(new GlobalJobListener(), EverythingMatcher.allJobs());
            scheduler.setJobFactory(new CustomOSGIJobFactory(this));

			
			registeredJobs = new HashMap<String, ICommonJob>();
			
			
		} catch (SchedulerException se) {
			logger.error("QuartzSchedulerHelper()", se);

		}

		JobDataMap jdm = new JobDataMap();
		jdm.put("Chave1", "Valor1");

		// define the job and tie it to our HelloJob class
		JobDetail job = newJob(HeartBeatJob.class)
				.withIdentity("job1", "group1").usingJobData(jdm).build();

		
		// Trigger the job to run now, and then repeat every 40 seconds
		Trigger trigger = newTrigger().withIdentity("trigger1", "group1")
				.startNow().withSchedule(cronSchedule("0/30 * * * * ?")).build();

		// Tell quartz to schedule the job using our trigger
		scheduler.scheduleJob(job, trigger);

		scheduler.start();

		logger.info("startScheduler() - end");
	}

	
	@Override
	public void registerJob(ICommonJob service) {
		logger.info("registerJob(ICommonJob) - start");

		

		JobDataMap jdm = new JobDataMap();
		jdm.put(ICommonJob.OSGI_JOB_NAME, service.getJobName());
		
		// define the job and tie it to our HelloJob class
		JobDetail job = newJob(service.getClass())
				.withIdentity(service.getJobName(), service.getJobGroup())
				.usingJobData(jdm)
				.build();

		
		// Trigger the job to run now, and then repeat every 40 seconds
		Trigger trigger = newTrigger().withIdentity("trigger."+service.getJobName(), "triggerg."+service.getJobGroup())
				.startNow().withSchedule(cronSchedule(service.getCronExpression())).build();

		// Tell quartz to schedule the job using our trigger
		try {
			
			service.setJobKey(job.getKey());
			scheduler.scheduleJob(job, trigger);		
			registeredJobs.put(service.getJobName(), service);
			
		} catch (SchedulerException e) {
			logger.error("registerJob(ICommonJob)", e);
			
			service.setJobKey(null);
			e.printStackTrace();
		}		
		
		logger.info("registerJob(ICommonJob) - end");
	}

	@Override
	public void unregisterJob(ICommonJob service) {
		logger.info("unregisterJob(ICommonJob) - start");
		
		registeredJobs.remove(service.getJobName());
		
		try {
			scheduler.deleteJob(service.getJobKey());
		} catch (SchedulerException e) {
			logger.error("unregisterJob(ICommonJob)", e);

			e.printStackTrace();
		}
		
		logger.info("unregisterJob(ICommonJob) - end");
	}

	
	@Override
	public void activate(ComponentContext context) {
		logger.info("activate(ComponentContext) - start");
		
		super.activate(context);
		
		
		logger.info("activate(ComponentContext) - ServiceName: "+getServiceName());
		
		try {
			startScheduler();
		} catch (Exception e) {
			
			logger.error("activate(ComponentContext)", e);
			e.printStackTrace();
			
		}
		
		logger.info("activate(ComponentContext) - end");
	}

	
	
	@Override
	public void deactivate(ComponentContext context) {

		logger.info("deactivate(ComponentContext) - begin");
		
		try {
			
			shutdownScheduler();
			
		} catch (Exception e) {
			
			logger.error("activate(ComponentContext)", e);
			e.printStackTrace();
			
		}
		
		super.deactivate(context);
		logger.info("deactivate(ComponentContext) - end");
		
	}

	
	@Override
	public ICommonJob getRegisteredJob(String jobServiceName) {
        
		return this.registeredJobs.get(jobServiceName);
	}
	
	
	

}
